--[[
* MapNotes 2.0
* File: MapNotes\MapNotes.lua
* $Revision: 138 $
* $Date: 2007-01-12 23:04:42 +0000 (Fri, 12 Jan 2007) $
* 
* Copyright (c) 2006-2007, Mery (Moritz Metelmann)
* All rights reserved.
* 
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* 
*    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
*    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
*    * Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
]]--

if (not MapNotes) then MapNotes = {}; end;
if (not MapNotes.zoneSortedList) then MapNotes.zoneSortedList = {}; end;
if (not MapNotes.Event) then MapNotes.Event = {}; end;

local L = MapNotes.Localization;

MapNotes.CreateNote = function(zone, x, y, title, titleColor, category, iconID, description, descriptionColor, creator, creationDate)
	-- date: a 12 digit number as string as in ddmmyyHHMMSS
	-- lookup if the hash is already used, if it is - throw an error.
	local noteID = MapNotes.NoteHash(zone, x, y);
	if (MapNotesSaved_NoteDB[noteID]) then return false; end; -- THROW AN VISIBLE ERROR!! LOL
	if (not creationDate) then creationDate = date("%d%m%y%H%M%S"); end;
	if (not creator) then creator = UnitName("player").."-"..GetRealmName(); end;
	MapNotesSaved_NoteDB[noteID] = {
		zone = zone,
		x = x,
		y = y,
		title = title,
		description = description,
		category = category,
		iconID = iconID,
		misc = strjoin("$", titleColor, descriptionColor, creator, creationDate, date("%d%m%y%H%m%S")),
	};
	-- writenote and insert the noteID into the zonesorted list.
	if (not MapNotes.zoneSortedList[zone]) then MapNotes.zoneSortedList[zone] = {}; end;
	table.insert(MapNotes.zoneSortedList[zone], noteID);
	MapLib.EventHandler.TriggerEvent("MAPNOTES_NOTE_CREATE", zone, noteID);
	MapLib.ForcePOIUpdate();
	return true;
end;

MapNotes.UpdateNote = function(noteID, title, titleColor, category, iconID, description, descriptionColor, creator, creationDate)
	local note;
	if (MapNotesSaved_NoteDB[noteID]) then note = MapNotesSaved_NoteDB[noteID]; else return; end;
	if (title) then note.title = title; end;
	if (category) then note.category = category; end;
	if (description) then note.description = description; end;
	if (iconID) then note.iconID = iconID; end;
	local orig_titleColor, orig_descriptionColor, orig_creator, orig_creationDate, _ = strsplit("$", note.misc);
	if (titleColor) then orig_titleColor = titleColor; end;
	if (descriptionColor) then orig_descriptionColor = descriptionColor; end;
	if (creator) then orig_creator = creator; end;
	if (creationDate) then orig_creationDate = creationDate; end;
	note.misc = strjoin("$", orig_titleColor, orig_descriptionColor, orig_creator, orig_creationDate, date("%d%m%y%H%m%S"));
	MapLib.EventHandler.TriggerEvent("MAPNOTES_NOTE_UPDATE", note.zone, noteID);
	MapLib.ForcePOIUpdate();
end;

MapNotes.DeleteNote = function(noteID)
	local zone;
	if (MapNotesSaved_NoteDB[noteID]) then
		zone = MapNotesSaved_NoteDB[noteID].zone;
		MapNotesSaved_NoteDB[noteID] = nil;
		for key, value in pairs(MapNotes.zoneSortedList) do
			for index, id in ipairs(value) do
				if (id == noteID) then table.remove(value, index); end;
			end;
		end;
	end;
	MapLib.EventHandler.TriggerEvent("MAPNOTES_NOTE_DELETE", zone, noteID);
	MapLib.ForcePOIUpdate();
end;

MapNotes.GetBasicNoteInfo = function(noteID)
	if (MapNotesSaved_NoteDB[noteID]) then
		return MapNotesSaved_NoteDB[noteID].title, MapNotesSaved_NoteDB[noteID].zone, MapNotes.Icon.GetIconTexture(MapNotesSaved_NoteDB[noteID].iconID, MapNotesSaved_NoteDB[noteID].category), MapNotesSaved_NoteDB[noteID].x, MapNotesSaved_NoteDB[noteID].y;
	end;
end;

MapNotes.OnLoad = function()
	local frame = CreateFrame("Frame", "MapNotesEventFrame")
	frame:SetScript("OnEvent", MapNotes.VariablesLoaded);
	frame:RegisterEvent("ADDON_LOADED");
end;

MapNotes.VariablesLoaded = function()
	MapNotesEventFrame:UnregisterEvent("ADDON_LOADED");
	if (not MapNotesSaved_NoteDB) then MapNotesSaved_NoteDB = { version = 1 }; end;
	if (not MapNotesSaved_Category or not MapNotesSaved_Category.version) then MapNotesSaved_Category = { version = 1 }; end;
	if (not MapNotesSaved_Category.categories) then MapNotesSaved_Category.categories = {}; end;
		-- Testing categories!
--~ 		tinsert(MapNotesSaved_Category.categories, {name = "Test 1", defaultIcon = 2});
--~ 		tinsert(MapNotesSaved_Category.categories, {name = "Test 2 rghbeiourgb erbg iuerbg ieruhbg uierhg eui", defaultIcon = 1});
--~ 		tinsert(MapNotesSaved_Category.categories, {name = "Test 3", defaultIcon = 1});
--~ 		tinsert(MapNotesSaved_Category.categories, {name = "Test 4", defaultIcon = 1});
--~ 		tinsert(MapNotesSaved_Category.categories, {name = "Test 5", defaultIcon = 3});
--~ 		tinsert(MapNotesSaved_Category.categories, {name = "Test 6", defaultIcon = 2});
--~ 		tinsert(MapNotesSaved_Category.categories, {name = "Test 7", defaultIcon = 2});
--~ 		tinsert(MapNotesSaved_Category.categories, {name = "Test 8", defaultIcon = 1});

	-- update the mapdatabase if version changed
	-- build the zonelist
	for noteID, note in pairs(MapNotesSaved_NoteDB) do
		if (noteID ~= "version") then
			if (not MapNotes.zoneSortedList[note.zone]) then MapNotes.zoneSortedList[note.zone] = {}; end;
			table.insert(MapNotes.zoneSortedList[note.zone], noteID);
		end;
	end;

	MapLib.POI.RegisterForPOI("MAPNOTES", L["Notes"], 5, MapNotes.BuiltSubmenuTable(), MapNotes.GetNumNotes, MapNotes.GetNote, MapNotes.Tooltip.BuildTooltip, false);

	MapLib.Menu.RegisterButton(L["Create New Note"], MapNotes.EditMenu.NewNote, function(mapID, x, y) return MapLib.IsZoneMap(); end)
	MapLib.POI.RegisterMenuButton(L["Edit Note"], MapNotes.EditMenu.EditNote, {"MAPNOTES"}, function() return true; end);
	MapLib.POI.RegisterMenuButton(L["Delete Note"], MapNotes.EditMenu.DeleteNote, {"MAPNOTES"}, function() return true; end);
end;

MapNotes.BuiltSubmenuTable = function()
	-- built the submenu
	-- add general + received
	local submenu = {
		{text = MapNotes.Category.generalCategory.name, texture = MapNotes.Icon.GetIconTexture(MapNotes.Category.generalCategory.defaultIcon), style = MapNotes.Category.generalCategory.name, default = true},
		{text = MapNotes.Category.receivedCategory.name, texture = MapNotes.Icon.GetIconTexture(MapNotes.Category.receivedCategory.defaultIcon), style = MapNotes.Category.receivedCategory.name, default = true},
	}
	for _, v in pairs(MapNotesSaved_Category.categories) do
		table.insert(submenu, {text = v.name, texture = MapNotes.Icon.GetIconTexture(v.defaultIcon), style = v.name, default = true});
	end;
	return submenu;
end;

MapNotes.GetNumNotes = function(zoneID)
	if (not zoneID) then zoneID = MapLib.mapShown; end;
	local num;
	if (MapNotes.zoneSortedList[zoneID]) then num = getn(MapNotes.zoneSortedList[zoneID]); else num = 0; end;
	return num;
end;

MapNotes.GetNote = function(index, zoneID)
	if (not zoneID) then zoneID = MapLib.mapShown; end;
	local note = MapNotesSaved_NoteDB[MapNotes.zoneSortedList[zoneID][index]];
	return MapNotes.zoneSortedList[zoneID][index], note.title, MapNotes.Icon.GetIconTexture(note.iconID, note.category), note.x, note.y, note.category, 5, nil; --(second last nil is note.category)
end;

-- This function was coded by Mikk
-- see http://www.wowwiki.com/StringHash
MapNotes.NoteHash = function(zone, xPos, yPos)
	local text = zone..xPos..yPos;
	local counter = 1;
	local len = string.len(text); 
	for i = 1, len, 3 do
		counter = math.fmod(counter*8161, 4294967279) +  -- 2^32 - 17: Prime!
		(string.byte(text,i)*16776193) +
		((string.byte(text,i+1) or (len-i+256))*8372226) +
		((string.byte(text,i+2) or (len-i+256))*3932164);
	end;
	return math.fmod(counter, 4294967291); -- 2^32 - 5: Prime (and different from the prime in the loop)
end;

MapNotes.OnLoad();